#include "sct/rtspserver/h264streamsource.h"

namespace sct
{
using namespace std;

CH264StreamSource::CH264StreamSource(CServerInterface * server):
		CStreamSource(server)
{
	setName(sct::toString("CH264StreamSource %p", this));
}

CH264StreamSource::~CH264StreamSource()
{
	;
}

enum ParseState
{
	PS_FoundOthers = SCT_ENUM_OFFSET,
	PS_FoundSPS,
	PS_FoundPPS,
};

void CH264StreamSource::onPutData(const void*p, const int len, const int64_t pts)
{

	///split sps pps, order is:sps->pps->others
	///strip the start code.
	uint32_t head;
	uint32_t head1;
	uint8_t* pStart;
	uint8_t* pCur;
	uint8_t* pLastHead;
	int state = 0;

	///check if the source format is right.
	if(len < 4)
	{
		SCT_LOGD("format wrong. size < 4");
		return;
	}
	memcpy(&head, p, sizeof(head));
	if( (0x1000000 != head) && (0x10000 != head) )
	{
		SCT_LOGD("format wrong. should start with 'START CODE'");
		return;
	}

	head = 0;
	head1 = 0;
	pStart = pCur = pLastHead = (uint8_t*)p;
	while(1)
	{
		memcpy(&head, pCur, 4);
		memcpy(&head1, pCur, 3);
		if(0x1000000 == head || 0x10000 == (head1&0xffffff))
		{
			if(pCur - pLastHead > 0)
			{
				CStreamSource::onPutData(pLastHead, pCur-pLastHead, pts);
				//SCT_LOG("state:%d", state);
			}

			if(0x1000000 == head)
			{
				pCur+=4;
			}
			else
			{
				pCur+=3;
			}
			pLastHead = pCur;

			switch(pCur[0]&0x1f)
			{
			case 7:
			{
				///found sps
				state = PS_FoundSPS;
				break;
			}

			case 8:
			{
				///found pps
				state = PS_FoundPPS;
				break;
			}

			default:
			{
				///found others
				state = PS_FoundOthers;
				break;
			}
			}
		}

		if(PS_FoundOthers == state)
		{
			CStreamSource::onPutData(pLastHead, len-(pLastHead-pStart), pts);
			//SCT_LOG("state:%d", state);
			break;
		}

		pCur++;
		if(pCur == (pStart+len) )
		{
			///reach the read, means not found others
			CStreamSource::onPutData(pLastHead, len-(pLastHead-pStart), pts);
			//SCT_LOG("state:%d", state);
			break;
		}
	}
}


}
